package org.luckyjourney.service.user.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.serializer.BeanContext;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.luckyjourney.config.QiNiuConfig;
import org.luckyjourney.constant.AuditStatus;
import org.luckyjourney.constant.RedisConstant;
import org.luckyjourney.entity.ApiConstant;
import org.luckyjourney.entity.File;
import org.luckyjourney.entity.consultants.TalConsultants;
import org.luckyjourney.entity.regularusers.RegularUsers;
import org.luckyjourney.entity.response.AuditResponse;
import org.luckyjourney.entity.user.*;
import org.luckyjourney.entity.video.Type;
import org.luckyjourney.entity.vo.*;
import org.luckyjourney.exception.BaseException;
import org.luckyjourney.holder.UserHolder;
import org.luckyjourney.mapper.regularusers.RegularUsersMapper;
import org.luckyjourney.mapper.user.PersonalLabelsMapper;
import org.luckyjourney.mapper.user.TrainingMapper;
import org.luckyjourney.mapper.user.UserMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.luckyjourney.mapper.user.UserRoleMapper;
import org.luckyjourney.service.FileService;
import org.luckyjourney.service.InterestPushService;
import org.luckyjourney.service.audit.ImageAuditService;
import org.luckyjourney.service.audit.TextAuditService;
import org.luckyjourney.service.user.FavoritesService;
import org.luckyjourney.service.user.FollowService;
import org.luckyjourney.service.user.UserService;
import org.luckyjourney.service.user.UserSubscribeService;
import org.luckyjourney.service.video.TypeService;
import org.luckyjourney.ume.ModulePacketType;
import org.luckyjourney.util.BaseContext;
import org.luckyjourney.util.MD5Utils;
import org.luckyjourney.util.RedisCacheUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static org.luckyjourney.constant.RedisConstant.USER_SEARCH_HISTORY_TIME;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author xhy
 * @since 2023-10-24
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private TypeService typeService;

    @Autowired
    private UserSubscribeService userSubscribeService;

    @Autowired
    private FollowService followService;

    @Autowired
    private RedisCacheUtil redisCacheUtil;

    @Autowired
    private FileService fileService;

    @Autowired
    private InterestPushService interestPushService;

    @Autowired
    private FavoritesService favoritesService;

    @Autowired
    private TextAuditService textAuditService;

    @Autowired
    private ImageAuditService imageAuditService;
    @Autowired
    UserMapper userMapper;
    @Autowired
    UserRoleMapper userRoleMapper;
    @Autowired
    UserService userService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;//防止乱码
    //咨询师表
    @Autowired
    RegularUsersMapper regularUsersMapper;

    @Autowired
    PersonalLabelsMapper personalLabelsMapper;
    @Autowired
    TrainingMapper trainingMapper;

    @Override
    public boolean register(RegisterVO registerVO) throws Exception {

        // 手机号是否存在
        final int count = count(new LambdaQueryWrapper<User>().eq(User::getPhone, registerVO.getPhone()));
        if (count == 1) {
            throw new BaseException("手机号已被注册");
        }
        String codeInSession = redisTemplate.opsForValue().get(registerVO.getPhone());
        if (ObjectUtil.isEmpty(codeInSession)) {
            throw new BaseException("验证码已失效");
        }

        if (ObjectUtil.isNotEmpty(codeInSession) && codeInSession.equals(registerVO.getCode())) {
            final User user = new User();
            user.setNickName("心理咨询");
            user.setPhone(registerVO.getPhone());
            user.setDescription("这个人很懒...");
            user.setCover(null);
            user.setOpenid(registerVO.getOpenid());
            user.setSettledStatus(0);
            user.setPassword(MD5Utils.GetMD5Code(registerVO.getPassword()));
            System.out.println("registerVO.getModuleId() = " + registerVO.getModuleId());
            if (registerVO.getModuleId() == (ModulePacketType.REGULARUSERS.getType())) {
                user.setModuleId(registerVO.getModuleId());
            } else {
                throw new BaseException("没有注册类型");
            }
            save(user);
            // 创建默认收藏夹
            final Favorites favorites = new Favorites();

            final UserRole userRole = new UserRole();
            userRole.setUserId(user.getId());
            userRole.setRoleId(18L);
            userRoleMapper.insert(userRole);
            favorites.setUserId(user.getId());
            favorites.setName("默认收藏夹");
            favoritesService.save(favorites);
            // 这里如果单独抽出一个用户配置表就好了,但是没有必要再搞个表
            user.setDefaultFavoritesId(favorites.getId());
            updateById(user);
            return true;
        }
        return false;
    }

    @Override
    public UserVO getInfo(Long userId) {

        final User user = getById(userId);
        if (ObjectUtils.isEmpty(user)) {
            return new UserVO();
        }
        final UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        // 查出关注数量
        final long followCount = followService.getFollowCount(userId);
        // 查出粉丝数量
        final long fansCount = followService.getFansCount(userId);
        if (ObjectUtil.isNotEmpty(user.getAvatar())) {
            File file = fileService.getById(user.getAvatar());
            String a = QiNiuConfig.CNAME + "/" + file.getFileKey();
            userVO.setA(a);
            userVO.setAvatar(file.getId());
        }
        if (ObjectUtil.isNotEmpty(user.getCover())) {
            File file = fileService.getById(user.getCover());
            String c = QiNiuConfig.CNAME + "/" + file.getFileKey();
            userVO.setC(c);
            userVO.setCover(file.getId());
        }
        Long currentId = BaseContext.getCurrentId();
        User user1 = userMapper.selectById(currentId);
        Integer moduleId = user1.getModuleId();
        // 获取自己的关注列表
        List<Long> followIds = followService.getFollowId(currentId, moduleId);
        //查看是否保函关注的人
        if (ObjectUtil.isNotEmpty(followIds)) {
            if (followIds.contains(userId)) {
                userVO.setStatus(true);
            } else {
                userVO.setStatus(false);
            }
        }

        userVO.setFollow(followCount);
        userVO.setFans(fansCount);
        return userVO;
    }


    public void initModel(ModelVO modelVO) {
        // 初始化模型
        interestPushService.initUserModel(modelVO.getUserId(), modelVO.getLabels());
    }

    @Override
    public Page<UserVO> getFollows(Long userId, BasePage basePage) {
        Page<UserVO> page = new Page<>();
        // 获取自己的关注列表
        final List<Follow> followIds = followService.getFollow(userId, basePage);
        System.out.println("followIds = " + followIds);
        if (ObjectUtils.isEmpty(followIds)) {
            return page;
        }
        ArrayList<UserVO> userList = new ArrayList<>();
        for (Follow follow : followIds) {
            //获取关注人的类型id 跟关注人的id
            Integer moduleId1 = follow.getModuleId();
            Long followId = follow.getFollowId();
            if (moduleId1 == 2) {
                RegularUsers regularUsers = regularUsersMapper.selectById(followId);
                UserVO userVO1 = new UserVO();
                BeanUtils.copyProperties(regularUsers, userVO1);
                if (ObjectUtil.isNotEmpty(regularUsers.getAvatar())) {
                    File file = fileService.getById(regularUsers.getAvatar());
                    String a = QiNiuConfig.CNAME + "/" + file.getFileKey();
                    userVO1.setA(a);
                    userVO1.setAvatar(file.getId());
                }
                // 获取粉丝列表 也就是对方的id （FollowId） 跟（moduleId1） 查询出自己粉丝
                List<Follow> fans = followService.getFans(userId, basePage);
                if (ObjectUtil.isNotEmpty(fans) && fans.size() > 0) {
                    for (Follow fan : fans) {
                        //从自己的粉丝 id 就是被谁关注的自己
                        Integer myselfId = fan.getMyselfId();
                        Long userId1 = fan.getUserId();
                        //关注自己的id 同样自己也关注对方
                        if (followId.equals(userId1) && moduleId1.equals(myselfId)) {
                            userVO1.setStatus(true);
                        } else {
                            userVO1.setStatus(false);
                        }
                    }
                } else {
                    userVO1.setStatus(false);
                }

                Integer moduleId = regularUsers.getModuleId();
                userVO1.setModuleId(moduleId);
                userList.add(userVO1);
            } else {
                User user = userMapper.selectById(followId);
                UserVO userVO1 = new UserVO();
                BeanUtils.copyProperties(user, userVO1);
                if (ObjectUtil.isNotEmpty(user.getAvatar())) {
                    File file = fileService.getById(user.getAvatar());
                    String a = QiNiuConfig.CNAME + "/" + file.getFileKey();
                    userVO1.setA(a);
                    userVO1.setAvatar(file.getId());
                }
                // 获取粉丝列表
                List<Follow> fans = followService.getFans(userId, basePage);
                for (Follow fan : fans) {
                    //粉丝id
                    Integer myselfId = fan.getMyselfId();
                    Long userId1 = fan.getUserId();

                    if (followId.equals(userId1) && moduleId1.equals(myselfId)) {
                        userVO1.setStatus(true);
                    } else {
                        userVO1.setStatus(false);
                    }
                }
                Integer moduleId = user.getModuleId();
                userVO1.setModuleId(moduleId);
                userList.add(userVO1);
            }
        }


        page.setRecords(userList);
        page.setTotal(userList.size());

        return page;
    }

    @Override
    public Page<UserVO> getFans(Long userId, BasePage basePage) {
        final Page<UserVO> page = new Page<>();

        // 获取粉丝列表   通过关注人的id查询出的是自己的粉丝
        List<Follow> fans = followService.getFans(userId, basePage);
        // 获取关注列表
        ArrayList<UserVO> userList = new ArrayList<>();
        for (Follow fan : fans) {
            //获取粉丝的类型id
            Integer myselfId = fan.getMyselfId();
            //获取粉丝的id
            Long userId1 = fan.getUserId();
            if (myselfId == 2) {
                //查询咨询师列表
                RegularUsers regularUsers = regularUsersMapper.selectById(userId1);
                UserVO userVO1 = new UserVO();
                BeanUtils.copyProperties(regularUsers, userVO1);
                if (ObjectUtil.isNotEmpty(regularUsers.getAvatar())) {
                    File file = fileService.getById(regularUsers.getAvatar());
                    String a = QiNiuConfig.CNAME + "/" + file.getFileKey();
                    userVO1.setA(a);
                    userVO1.setAvatar(file.getId());
                }
                // 获取关注列表
                List<Follow> followIds = followService.getFollow(userId, basePage);
                if (ObjectUtil.isNotEmpty(followIds) && followIds.size() > 0) {
                    for (Follow follow : followIds) {
                        //粉丝id
                        Integer moduleId1 = follow.getModuleId();
                        Long followId = follow.getFollowId();
                        if (moduleId1 == 2) {
                            ///查看是否关注  通过查询自己的关注列表  判断是否为互相关注
                            if (followId.equals(userId1) && moduleId1.equals(myselfId)) {
                                userVO1.setStatus(true);
                            } else {
                                userVO1.setStatus(false);
                            }
                        }

                    }
                } else {
                    userVO1.setStatus(false);
                }
                Integer moduleId = regularUsers.getModuleId();
                userVO1.setModuleId(moduleId);
                userList.add(userVO1);
            } else {
                //查询用户表
                User user = userMapper.selectById(userId1);
                UserVO userVO1 = new UserVO();
                BeanUtils.copyProperties(user, userVO1);
                if (ObjectUtil.isNotEmpty(user.getAvatar())) {
                    File file = fileService.getById(user.getAvatar());
                    String a = QiNiuConfig.CNAME + "/" + file.getFileKey();
                    userVO1.setA(a);
                    userVO1.setAvatar(file.getId());
                }
                // 获取关注列表
                List<Follow> followIds = followService.getFollow(userId, basePage);
                if (ObjectUtil.isNotEmpty(followIds) && followIds.size() > 0) {
                    for (Follow follow : followIds) {
                        //获取关注人的类型id
                        Integer moduleId1 = follow.getModuleId();
                        //获取要查询的关注列表的id
                        Long followId = follow.getFollowId();
                        if (moduleId1 == 1) {
                            if (followId.equals(userId1) && moduleId1.equals(myselfId)) {
                                userVO1.setStatus(true);
                            } else {
                                userVO1.setStatus(false);
                            }
                        }

                    }
                } else {
                    userVO1.setStatus(false);
                }
                Integer moduleId = user.getModuleId();
                userVO1.setModuleId(moduleId);
                userList.add(userVO1);
            }


        }

        page.setRecords(userList);
        page.setTotal(userList.size());
        return page;
    }

    private Map<Long, User> getBaseInfoUserToMap(Collection<Long> userIds) {
        List<User> users = new ArrayList<>();
        if (!ObjectUtils.isEmpty(userIds)) {
            users = list(new LambdaQueryWrapper<User>().in(User::getId, userIds)
                    .select(User::getId, User::getNickName, User::getDescription
                            , User::getSex, User::getAvatar));
        }
        return users.stream().collect(Collectors.toMap(User::getId, Function.identity()));
    }

    @Override
    public List<User> list(Collection<Long> userIds) {
        return list(new LambdaQueryWrapper<User>().in(User::getId, userIds)
                .select(User::getId, User::getNickName, User::getSex, User::getAvatar, User::getDescription));
    }

    @Override
    @Transactional
    public void subscribe(Set<Long> typeIds) {
        if (ObjectUtils.isEmpty(typeIds)) {
            return;
        }
        // 校验分类
        final Collection<Type> types = typeService.listByIds(typeIds);
        if (typeIds.size() != types.size()) {
            throw new BaseException("不存在的分类");
        }
        final Long userId = UserHolder.get();
        final ArrayList<UserSubscribe> userSubscribes = new ArrayList<>();
        for (Long typeId : typeIds) {
            final UserSubscribe userSubscribe = new UserSubscribe();
            userSubscribe.setUserId(userId);
            userSubscribe.setTypeId(typeId);
            userSubscribes.add(userSubscribe);
        }
        // 删除之前的
        userSubscribeService.remove(new LambdaQueryWrapper<UserSubscribe>().eq(UserSubscribe::getUserId, userId));
        userSubscribeService.saveBatch(userSubscribes);
        // 初始化模型
        final ModelVO modelVO = new ModelVO();
        modelVO.setUserId(UserHolder.get());
        // 获取分类下的标签
        List<String> labels = new ArrayList();
        for (Type type : types) {
            labels.addAll(type.buildLabel());
        }
        modelVO.setLabels(labels);
        initModel(modelVO);

    }

    @Override
    public Collection<Type> listSubscribeType(Long userId) {
        if (userId == null) {
            return Collections.EMPTY_SET;
        }
        final List<Long> typeIds = userSubscribeService.list(new LambdaQueryWrapper<UserSubscribe>().eq(UserSubscribe::getUserId, userId))
                .stream().map(UserSubscribe::getTypeId).collect(Collectors.toList());
        if (ObjectUtils.isEmpty(typeIds)) return Collections.EMPTY_LIST;
        final List<Type> types = typeService.list(new LambdaQueryWrapper<Type>()
                .in(Type::getId, typeIds).select(Type::getId, Type::getName, Type::getIcon));
        return types;
    }

    @Override
    public boolean follows(Follow follow) {
        //自己的id（也就是数据的粉丝id）
        final Long userId = UserHolder.get();
        //要关注人的id
        Long followId = follow.getFollowId();
        //要关注人的类型id
        Integer moduleId = follow.getModuleId();
        if (ObjectUtil.isEmpty(followId) && ObjectUtil.isEmpty(moduleId)) {
            throw new BaseException("请选择要关注的用户");
        }

        return followService.follows(followId, userId, moduleId);
    }

    @Override
    public void updateUserModel(UserModel userModel) {
        interestPushService.updateUserModel(userModel);
    }

    @Override
    public Boolean findPassword(FindPWVO findPWVO) {
        String codeInSession = redisTemplate.opsForValue().get(findPWVO.getPhone());
        if (ObjectUtil.isEmpty(codeInSession)) {
            throw new BaseException("验证码已失效");
        }
        if (ObjectUtil.isNotEmpty(codeInSession) && codeInSession.equals(findPWVO.getCode())) {

            User user = userMapper.selectById(findPWVO.getPhone());
            if (ObjectUtil.isEmpty(user)) {
                throw new BaseException("该手机号用户不存在，请注册");
            }
            User user1 = new User();
            user1.setPassword(MD5Utils.GetMD5Code(findPWVO.getNewPassword()));
            user1.setPhone(findPWVO.getPhone());
            int count = userMapper.updateById(user1);
            if (count > 0) {
                return true;
            }
        }
        return false;

    }

    @Override
    public void updateUser(UpdateUserVO user) throws Exception {

        final Long userId = UserHolder.get();

        final User oldUser = getById(userId);
        // 需要审核
        if (!oldUser.getNickName().equals(user.getNickName())) {
            oldUser.setNickName(user.getNickName());
            final AuditResponse audit = textAuditService.audit(user.getNickName());
            if (!audit.getAuditStatus().equals(AuditStatus.SUCCESS)) {
                throw new BaseException(audit.getMsg());
            }
        }
        if (!ObjectUtils.isEmpty(user.getDescription()) && !oldUser.getDescription().equals(user.getDescription())) {
            oldUser.setDescription(user.getDescription());
            final AuditResponse audit = textAuditService.audit(user.getNickName());
            if (!audit.getAuditStatus().equals(AuditStatus.SUCCESS)) {
                throw new BaseException(audit.getMsg());
            }
        }
        if (!Objects.equals(user.getAvatar(), oldUser.getAvatar()) && !StringUtils.isEmpty(user.getAvatar())) {
            final AuditResponse audit = imageAuditService.audit(fileService.getById(user.getAvatar()).getFileKey());
            if (!audit.getAuditStatus().equals(AuditStatus.SUCCESS)) {
                throw new BaseException(audit.getMsg());
            }
            oldUser.setAvatar(user.getAvatar());
        }

        /*if (!ObjectUtils.isEmpty(user.getDefaultFavoritesId())) {
            // 校验收藏夹
            favoritesService.exist(userId, user.getDefaultFavoritesId());
        }*/


        if (!StringUtils.isEmpty(user.getSex())) {
            oldUser.setSex(user.getSex());
        }

        oldUser.setDefaultFavoritesId(user.getDefaultFavoritesId());
        oldUser.setCover(user.getCover());
        updateById(oldUser);
    }

    @Override
    public Collection<String> searchHistory(Long userId) {
        List<String> searchs = new ArrayList<>();
        if (userId != null) {
            searchs.addAll(redisCacheUtil.zGet(RedisConstant.USER_SEARCH_HISTORY + userId));
            searchs = searchs.subList(0, searchs.size() < 20 ? searchs.size() : 20);
        }
        return searchs;
    }

    @Override
    @Async
    public void addSearchHistory(Long userId, String search) {
        if (userId != null) {
            redisCacheUtil.zadd(RedisConstant.USER_SEARCH_HISTORY + userId, new Date().getTime(), search, USER_SEARCH_HISTORY_TIME);
        }
    }

    @Override
    public void deleteSearchHistory(Long userId) {
        if (userId != null) {
            redisCacheUtil.del(RedisConstant.USER_SEARCH_HISTORY + userId);
        }
    }

    @Override
    public Collection<Type> listNoSubscribeType(Long userId) {

        // 获取用户订阅的分类
        final Set<Long> set = listSubscribeType(userId).stream().map(Type::getId).collect(Collectors.toSet());
        // 获取所有分类
        final List<Type> allType = typeService.list(null);

        final ArrayList<Type> types = new ArrayList<>();
        for (Type type : allType) {
            if (!set.contains(type.getId())) {
                types.add(type);
            }
        }

        return types;
    }

    public List<User> getUsers(Collection<Long> ids) {
        final Map<Long, User> userMap = listByIds(ids).stream().collect(Collectors.toMap(User::getId, Function.identity()));
        List<User> result = new ArrayList<>();
        for (Long followId : ids) {
            final User user = new User();
            user.setId(followId);
            final User u = userMap.get(followId);
            user.setNickName(u.getNickName());
            user.setSex(u.getSex());
            user.setDescription(u.getDescription());
            result.add(user);
        }
        return result;
    }
}
